package com.runjian.rundo.iot.agent.business.control.event;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

import com.alibaba.fastjson2.annotation.JSONField;
import com.runjian.rundo.iot.agent.business.control.enums.ControlResult;
import com.runjian.rundo.iot.agent.business.event.DeviceEvent;
import com.runjian.rundo.iot.agent.common.entity.CommonDeviceCommand;

import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * 设备控制响应事件
 *
 * @author LiPan
 */
@Slf4j
@Getter
@Setter
public class DeviceControlResponseEvent extends DeviceEvent {

    /**
     * 控制指标项标识符
     */
    @JSONField(deserialize = false, serialize = false)
    private CommonDeviceCommand deviceCommand;

    /**
     * 控制反馈时间
     */
    @JSONField(name = "time",format = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private ZonedDateTime callbackTime;

    /**
     * 控制反馈指标项
     */
    private String series;

    /**
     * 错误信息
     */
    private final String message;

    /**
     * 控制结果
     */
    @JSONField(name = "status")
    private final ControlResult controlResult;

    /**
     * 是否全部反馈
     */
    @JSONField(deserialize = false, serialize = false)
    private Boolean isAssCallback = Boolean.TRUE;

    /**
     * 控制失败
     *
     * @param deviceId 设备 Id
     * @param deviceCommand 控制数据
     * @param errorMessage 异常内容
     * @return 设备控制反馈事件
     */
    public static DeviceControlResponseEvent failed(String deviceId, CommonDeviceCommand deviceCommand, String errorMessage) {
        if (log.isDebugEnabled()) {
            log.debug("构建设备控制失败响应事件：设备Id:{}, 控制数据:{}, 控制失败描述 :{}", deviceId, deviceCommand, errorMessage);
        }
        return new DeviceControlResponseEvent(deviceId, deviceCommand, ControlResult.FAILED, StrUtil.EMPTY, errorMessage);
    }

    /**
     * 控制成功
     *
     * @param deviceId 设备 Id
     * @param deviceCommand 控制数据
     * @return 设备控制反馈事件
     */
    public static DeviceControlResponseEvent success(String deviceId, CommonDeviceCommand deviceCommand) {
        if (log.isDebugEnabled()) {
            log.debug("构建设备控制成功响应事件：设备Id:{}, 控制数据:{}, ", deviceId, deviceCommand);
        }
        return new DeviceControlResponseEvent(deviceId, deviceCommand, ControlResult.SUCCESS, StrUtil.EMPTY, "成功");
    }

    /**
     * 控制失败
     *
     * @param deviceId 设备 Id
     * @param deviceCommand 控制数据
     * @param errorMessage 异常内容
     * @return 设备控制反馈事件
     */
    public static DeviceControlResponseEvent failed(String deviceId, CommonDeviceCommand deviceCommand, String series,
        String errorMessage) {
        if (log.isDebugEnabled()) {
            log.debug("构建设备控制失败响应事件：设备Id:{}, 控制数据:{}, 控制失败描述 :{}", deviceId, deviceCommand, errorMessage);
        }
        return new DeviceControlResponseEvent(deviceId, deviceCommand, ControlResult.FAILED, series, errorMessage);
    }

    /**
     * 控制成功
     *
     * @param deviceId 设备 Id
     * @param deviceCommand 控制数据
     * @return 设备控制反馈事件
     */
    public static DeviceControlResponseEvent success(String deviceId, CommonDeviceCommand deviceCommand, String series) {
        if (log.isDebugEnabled()) {
            log.debug("构建设备控制成功响应事件：设备Id:{}, 控制数据:{}, ", deviceId, deviceCommand);
        }
        return new DeviceControlResponseEvent(deviceId, deviceCommand, ControlResult.SUCCESS, series, "成功");
    }

    private DeviceControlResponseEvent(String deviceId, CommonDeviceCommand deviceCommand, ControlResult controlResult, String series,
        String message) {
        super(deviceId);
        this.callbackTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC"));
        // 处理待反馈数据
        if (StrUtil.isNotBlank(series)) {
            // 已反馈的对象
            deviceCommand.addCallbackSeries(series);
            this.isAssCallback = Boolean.FALSE;
        } else {
            this.isAssCallback = Boolean.TRUE;
        }
        this.controlResult = controlResult;
        this.message = message;
        this.series = series;
        this.deviceCommand = deviceCommand;
    }

    public String getResultCode() {
        return this.controlResult.getCode();
    }
}
